#ifndef _VIDEO_VECTOR2_HPP
#define _VIDEO_VECTOR2_HPP

#include "../common.hpp"
#include <utility>

namespace yep
{
    using namespace rel_ops;
    /**
     * @brief A generic 2d Vector
     *
     * Several methods uses angle as parameter. The angle in that cases is always on radian
     *  and starts on right {1, 0} and grows @b clockwise.
     **/
    class Vector2
    {
    public:
        double x, y;

        /**
         * @brief Default constructor
         *
         * Sets the default values to zero.
         */
        Vector2()
        {
        	x = y = 0;
        }

        /**
         * @brief Creates a Vector2 based on position.
         **/
        Vector2(double x, double y)
        {
            this->x = x;
            this->y = y;
        }

        /**
         * @brief Creates a Vector2 based on angle.
         *
         * It will generate the x and y axices from the angle and the unitary length.
         *  To get a different length, just mutiply the result to the desired length;
         **/
        Vector2(double angle)
        {
            x = cos(angle);
            y = sin(angle);
        }

        /**
         * @brief Adds this vector to another one.
         **/
        Vector2 &operator +=(const Vector2 &other)
        {
            x += other.x;
            y += other.y;
            return *this;
        }

        /**
         * @brief Adds to vectors.
         **/
        Vector2 operator +(const Vector2 &other) const
        {
            return Vector2(*this)+=other;
        }

        /**
         * @brief Mutiply this vector to a scalar
         **/
        Vector2 &operator *=(double scalar)
        {
            x *= scalar;
            y *= scalar;
            return *this;
        }

        /**
         * @brief Mutiply a vector to a scalar
         **/
        Vector2 operator *(double scalar) const
        {
            return Vector2(*this)*=scalar;
        }

        /**
         * @brief Inverts the signal.
         **/
        Vector2 operator -() const
        {
            return Vector2(-x, -y);
        }

        /**
         * @brief Subctracts.
         **/
        Vector2 &operator -=(const Vector2 &other)
        {
            return *this += (-other);
        }

        /**
         * @brief Subctracts.
         **/
        Vector2 operator -(const Vector2 &other) const
        {
            return *this + (-other);
        }

        /**
         * @brief Return if it is the same
         *
         * It
         **/
        bool operator == (const Vector2 &other) const
        {
            return x == other.x && y == other.y;
        }

        /**
         * @brief Returns the distance between this and other vectors.
         **/
        double distance(const Vector2 &other) const
        {
            return sqrt(pow(x-other.x, 2) + pow(y-other.y, 2));
        }

        /**
         * @brief Returns the length of the vector (the distance from the origin).
         **/
        double length() const
        {
            return sqrt(pow(x, 2) + pow(y, 2));
        }

        /**
         * @brief Changes the length of the vector (the distance from the origin).
         **/
        void length(double value)
        {
            double len = length();
            x = x / len * value;
            y = y / len * value;
        }

        /**
         * @brief Returns the angle of the vector.
         **/
        double angle() const
        {
            return atan2(y, x);
        }

        /**
         * @brief Set Angle
         * @param value the new angle
         */
        void angle(double value)
        {
            double len = length();
            x = cos(value) * len;
            y = sin(value) * len;
        }

        bool before(const Vector2 &other) const
        {
            return x < other.x && y < other.y;
        }

        bool after(const Vector2 &other) const
        {
            return x > other.x && y > other.y;
        }

        /**
         * @brief the zero vector {0,0}
         **/
        static const Vector2 ZERO;

        /**
         * @brief the smallest vector {MIN,MIN}
         **/
        static const Vector2 MIN;

        /**
         * @brief the largest vector {MAX,MAX}
         **/
        static const Vector2 MAX;

        /**
         * @brief Convert to SDL_Rect
         **/
        operator SDL_Rect() const
        {
            return {static_cast<Sint16>(x), static_cast<Sint16>(y)};
        }

        /**
         * @brief Convert to SDL_Rect*
         *
         * The value is guaranteed to be corArea only until the next calling of this method.
         **/
        operator SDL_Rect*() const;
    };

}

#endif // _VIDEO_VECTOR2_HPP

